package git.soulbgm;

import org.apache.commons.net.ntp.NtpV3Impl;
import org.apache.commons.net.ntp.NtpV3Packet;
import org.apache.commons.net.ntp.TimeInfo;
import org.apache.commons.net.ntp.TimeStamp;

import java.net.DatagramPacket;

/**
 * 时间同步工具类
 *
 * @author SoulBGM
 * @date 2022/11/29 14:42
 */
public class NtpdateUtil {

    private final static LogUtil LOG = new LogUtil(NtpdateUtil.class);

    /**
     * 获取ntp请求数据包
     *
     * @return {@link byte[]}
     */
    public static byte[] getNtpRequestPacket() {
        NtpV3Packet message = new NtpV3Impl();
        message.setMode(NtpV3Packet.MODE_CLIENT);
        message.setVersion(NtpV3Packet.VERSION_3);
        message.setTransmitTime(TimeStamp.getCurrentTime());
        return message.getDatagramPacket().getData();
    }

    /**
     * 获得时间同步响应数据包
     *
     * @param rcvTime 接收时间
     * @param data    数据
     */
    public static byte[] getNtpResponsePacket(long rcvTime, byte[] data) {
        NtpV3Packet message = new NtpV3Impl();
        message.setDatagramPacket(new DatagramPacket(data, data.length));
        if (message.getMode() == NtpV3Packet.MODE_CLIENT) {
            return getNtpResponsePacket(rcvTime, message);
        }
        return new byte[0];
    }

    /**
     * 获得时间同步响应数据包
     *
     * @param rcvTime 接收时间
     * @param message NtpV3报文
     * @return {@link byte[]}
     */
    private static byte[] getNtpResponsePacket(long rcvTime, NtpV3Packet message) {
        NtpV3Packet response = new NtpV3Impl();

        response.setStratum(1);
        response.setMode(NtpV3Packet.MODE_SERVER);
        response.setVersion(NtpV3Packet.VERSION_3);
        response.setPrecision(-20);
        response.setPoll(0);
        response.setRootDelay(62);
        response.setRootDispersion((int) (16.51 * 65.536));

        // originate time as defined in RFC-1305 (t1)
        response.setOriginateTimeStamp(message.getTransmitTimeStamp());
        // Receive Time is time request received by server (t2)
        response.setReceiveTimeStamp(TimeStamp.getNtpTime(rcvTime));
        response.setReferenceTime(response.getReceiveTimeStamp());
        // LCL (Undisciplined Local Clock)
        response.setReferenceId(0x4C434C00);

        // Transmit time is time reply sent by server (t3)
        response.setTransmitTime(TimeStamp.getNtpTime(System.currentTimeMillis()));
        return response.getDatagramPacket().getData();
    }

    /**
     * 处理NTP包
     *
     * @param data 数据
     */
    public static void handleNtpPacket(byte[] data) {
        // 进行数据处理
        NtpV3Packet message = new NtpV3Impl();
        message.setDatagramPacket(new DatagramPacket(data, data.length));
        // 创建TimeInfo消息容器，但不要预先计算细节
        TimeInfo timeInfo = new TimeInfo(message, System.currentTimeMillis(), true);
        TimeStamp timeStamp = timeInfo.getMessage().getTransmitTimeStamp();
        long time = timeStamp.getTime();
        CmdResult result = CmdUtil.updateSystemDateTime(time);
        if (result.isSuccess()) {
            LOG.info("时间同步成功, 偏移毫秒数:{}", timeInfo.getOffset());
        } else {
            LOG.error("时间同步失败, 偏移毫秒数:{}, 失败原因:{}", timeInfo.getOffset(), result.getOutput());
        }
    }

}
